/**
* @file  protocol.c
* @brief this file contains protocol analysis and construct response function when received zigbee module send message
* @author qinlang
* @date 2022.05.06
* @par email:qinlang.chen@tuya.com
* @copyright HANGZHOU TUYA INFORMATION TECHNOLOGY CO.,LTD
* @par company
* http://www.tuya.com
*/

#include "zigbee.h"

#include "glh_typedef.h"

extern void DpDownloadMixRgbcwHandle(const unsigned char value[], unsigned short length);
extern void DpDownloadMixLightSceneHandle(const unsigned char value[], unsigned short length);
extern void DpDownloadSwitchLedHandle(BOOL bSwitch);
extern void DpDownloadSwitchNightLightHandle(BOOL bSwitch);
extern void DpDownloadCountdownHandle(uint32 u32CountDown);
extern void AllDataUpdate(void);
extern void DpDownloadMusicDataHandle(const unsigned char value[], unsigned short length);
extern void DpDownloadDoNotDsturbHandle(BOOL bSwitch);
extern void ZigbeeWorkStateEvent(unsigned char zigbee_work_state);
/******************************************************************************
                                移植须知:
1:MCU必须在while中直接调用mcu_api.c内的zigbee_uart_service()函数
2:程序正常初始化完成后,建议不进行关串口中断,如必须关中断,关中断时间必须短,关中断会引起串口数据包丢失
3:请勿在中断/定时器中断内调用上报函数
******************************************************************************/
/******************************************************************************
                              第一步:初始化
1:在需要使用到zigbee相关文件的文件中include "zigbee.h"
2:在MCU初始化中调用mcu_api.c文件中的zigbee_protocol_init()函数
3:将MCU串口单字节发送函数填入protocol.c文件中uart_transmit_output函数内,并删除#error
4:在MCU串口接收函数中调用mcu_api.c文件内的uart_receive_input函数,并将接收到的字节作为参数传入
5:单片机进入while循环后调用mcu_api.c文件内的zigbee_uart_service()函数

6:mcu何时开启zigbee模块配网，当zigbee模块查询到mcu的产品信息之后，或者zigbee模块发送了当前网络状态
给到mcu，查询pid信息会在上电5秒之后发送,对接部分zigbee老版本通用对接固件低功耗版本尤其需要注意不要
在第一次确认波特率的时候提前唤醒或者发送串口给zigbee模组，有概率导致zigbee模组波特率存储失败。

7：上电之后，mcu何时上报数据给网关合适，在收到网络状态为已配网，或者接收到读取dp数据的时候。
8: 在mcu ota过程中发送固件内容请求未收到zigbee模块的应答时，需要mcu端做好超时重新请求的处理，和存储image
处理，校验和可以自行设计或者使用参考。
******************************************************************************/

/******************************************************************************
                        1:dp数据点序列类型对照表
          **此为自动生成代码,如在开发平台有相关修改请重新下载MCU_SDK**         
******************************************************************************/

///> dp data list, this will be generated by cloud platform
const DOWNLOAD_CMD_S download_cmd[] =
{
  {DPID_SWITCH_LED, DP_TYPE_BOOL},
  {DPID_WORK_MODE, DP_TYPE_ENUM},
  {DPID_BRIGHT_VALUE, DP_TYPE_VALUE},
  {DPID_TEMP_VALUE, DP_TYPE_VALUE},
  {DPID_COLOUR_DATA, DP_TYPE_STRING},
  {DPID_SCENE_DATA, DP_TYPE_STRING},
  {DPID_COUNTDOWN, DP_TYPE_VALUE},
  {DPID_MUSIC_DATA, DP_TYPE_STRING},
  {DPID_CONTROL_DATA, DP_TYPE_STRING},
  {DPID_RHYTHM_MODE, DP_TYPE_RAW},
  {DPID_SLEEP_MODE, DP_TYPE_RAW},
  {DPID_WAKEUP_MODE, DP_TYPE_RAW},
  {DPID_POWER_MEMORY, DP_TYPE_RAW},
  {DPID_DO_NOT_DISTURB, DP_TYPE_BOOL},
  {DPID_SWITCH_GRADIENT, DP_TYPE_RAW},
  {DPID_MIX_LIGHT_SCENE, DP_TYPE_RAW},
  {DPID_MIX_RGBCW, DP_TYPE_RAW},
  {DPID_SEGMENT_DIMMING, DP_TYPE_RAW},
  {DPID_SWITCH_NIGHT_LIGHT, DP_TYPE_BOOL},
  {DPID_ZLL_VALUE, DP_TYPE_VALUE},
  {DPID_CYCLE_TIMING, DP_TYPE_RAW},
  {DPID_RANDOM_TIMING, DP_TYPE_RAW},
};


/******************************************************************************
                           2:串口单字节发送函数
请将MCU串口发送函数填入该函数内,并将接收到的数据作为参数传入串口发送函数
******************************************************************************/

static void report_mcu_ota_result(unsigned char  res);


/**
* @brief encapsulates a generic send function, developer should use their own function to completing this fuction 
* @param[in] {value} send signle data 
* @return  void
*/
void uart_transmit_output(unsigned char value)
{
//  #error "please use your own uart send fuction complete this fuction, exmaple"
/*
*  //demo:
*  extern void Uart_PutChar(unsigned char value);
*  Uart_PutChar(value);	                             
*/
    extern void GLHUART_SendByte(uint8 u8Byte);
    
    GLHUART_SendByte(value);
}

/******************************************************************************
                           第二步:实现具体用户函数
1:APP下发数据处理
2:数据上报处理
******************************************************************************/

/******************************************************************************
                            1:所有数据上报处理
当前函数处理全部数据上报(包括可下发/可上报和只上报)
  需要用户按照实际情况实现:
  1:需要实现可下发/可上报数据点上报
  2:需要实现只上报数据点上报
此函数为MCU内部必须调用
用户也可调用此函数实现全部数据上报
******************************************************************************/

//自动化生成数据上报函数

/**
* @brief Upload all dp information of the system, and realize the synchronization of APP and muc data
* @param[in] {void}
* @return  void
*/
void all_data_update(void)
{
//  #error "mcu must realize function internal function"
   /*
  * these fucntion will be generated by cloud platform, but when use these function must reference the function in  mcu_api.c
 */
//     mcu_dp_bool_update(DPID_SWITCH_LED,当前开关); //BOOL型数据上报;
//    mcu_dp_enum_update(DPID_WORK_MODE,当前模式); //枚举型数据上报;
//    mcu_dp_value_update(DPID_BRIGHT_VALUE,当前亮度值); //VALUE型数据上报;
//    mcu_dp_value_update(DPID_TEMP_VALUE,当前冷暖值); //VALUE型数据上报;
//    mcu_dp_string_update(DPID_COLOUR_DATA,当前彩光指针,当前彩光数据长度); //STRING型数据上报;
//    mcu_dp_string_update(DPID_SCENE_DATA,当前情景指针,当前情景数据长度); //STRING型数据上报;
//    mcu_dp_value_update(DPID_COUNTDOWN,当前倒计时剩余时间); //VALUE型数据上报;
//    mcu_dp_raw_update(DPID_RHYTHM_MODE,当前生物节律指针,当前生物节律数据长度); //RAW型数据上报;
//    mcu_dp_raw_update(DPID_SLEEP_MODE,当前入睡指针,当前入睡数据长度); //RAW型数据上报;
//    mcu_dp_raw_update(DPID_WAKEUP_MODE,当前唤醒指针,当前唤醒数据长度); //RAW型数据上报;
//    mcu_dp_raw_update(DPID_POWER_MEMORY,当前上电状态指针,当前上电状态数据长度); //RAW型数据上报;
//    mcu_dp_bool_update(DPID_DO_NOT_DISTURB,当前勿扰模式); //BOOL型数据上报;
//    mcu_dp_raw_update(DPID_SWITCH_GRADIENT,当前开关渐变指针,当前开关渐变数据长度); //RAW型数据上报;
//    mcu_dp_raw_update(DPID_MIX_LIGHT_SCENE,当前混光场景指针,当前混光场景数据长度); //RAW型数据上报;
//    mcu_dp_raw_update(DPID_MIX_RGBCW,当前混光指针,当前混光数据长度); //RAW型数据上报;
//    mcu_dp_raw_update(DPID_SEGMENT_DIMMING,当前分段调光指针,当前分段调光数据长度); //RAW型数据上报;
//    mcu_dp_bool_update(DPID_SWITCH_NIGHT_LIGHT,当前夜灯开关); //BOOL型数据上报;
//    mcu_dp_value_update(DPID_ZLL_VALUE,当前zigbee light link阀值); //VALUE型数据上报;
//    mcu_dp_raw_update(DPID_CYCLE_TIMING,当前循环定时指针,当前循环定时数据长度); //RAW型数据上报;
//    mcu_dp_raw_update(DPID_RANDOM_TIMING,当前随机定时指针,当前随机定时数据长度); //RAW型数据上报;

    AllDataUpdate();
}

/******************************************************************************
                                WARNING!!!    
                            2:所有数据上报处理
自动化代码模板函数,具体请用户自行实现数据处理
******************************************************************************/

///> this will realize by  cloud platform

/*****************************************************************************
函数名称 : dp_download_switch_led_handle
功能描述 : 针对DPID_SWITCH_LED的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_switch_led_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为BOOL
    unsigned char ret;
    //0:off/1:on
    unsigned char switch_led;
    
    switch_led = mcu_get_dp_download_bool(value,length);
    
    DpDownloadSwitchLedHandle(switch_led);
    
    if(switch_led == 0) {
        //bool off
    }else {
        //bool on
    }
  
    //There should be a report after processing the DP
    ret = mcu_dp_bool_update(DPID_SWITCH_LED,switch_led);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_work_mode_handle
功能描述 : 针对DPID_WORK_MODE的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_work_mode_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为ENUM
    unsigned char ret;
    unsigned char work_mode;
    
    work_mode = mcu_get_dp_download_enum(value,length);
    switch(work_mode) {
        case 0:
        break;
        
        case 1:
        break;
        
        case 2:
        break;
        
        case 3:
        break;
        
        default:
    
        break;
    }
    
    //There should be a report after processing the DP
    ret = mcu_dp_enum_update(DPID_WORK_MODE, work_mode);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_bright_value_handle
功能描述 : 针对DPID_BRIGHT_VALUE的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_bright_value_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为VALUE
    unsigned char ret;
    unsigned long bright_value;
    
    bright_value = mcu_get_dp_download_value(value,length);
    /*
    //VALUE type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_value_update(DPID_BRIGHT_VALUE,bright_value);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_temp_value_handle
功能描述 : 针对DPID_TEMP_VALUE的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_temp_value_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为VALUE
    unsigned char ret;
    unsigned long temp_value;
    
    temp_value = mcu_get_dp_download_value(value,length);
    /*
    //VALUE type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_value_update(DPID_TEMP_VALUE,temp_value);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_colour_data_handle
功能描述 : 针对DPID_COLOUR_DATA的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_colour_data_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为STRING
    unsigned char ret;
    /*
    //STRING type data processing
    unsigned char string_data[8];
    
    string_data[0] = value[0];
    string_data[1] = value[1];
    string_data[2] = value[2];
    string_data[3] = value[3];
    string_data[4] = value[4];
    string_data[5] = value[5];
    string_data[6] = value[6];
    string_data[7] = value[7];
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_string_update(DPID_COLOUR_DATA,value, length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_scene_data_handle
功能描述 : 针对DPID_SCENE_DATA的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_scene_data_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为STRING
    unsigned char ret;
    /*
    //STRING type data processing
    unsigned char string_data[8];
    
    string_data[0] = value[0];
    string_data[1] = value[1];
    string_data[2] = value[2];
    string_data[3] = value[3];
    string_data[4] = value[4];
    string_data[5] = value[5];
    string_data[6] = value[6];
    string_data[7] = value[7];
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_string_update(DPID_SCENE_DATA,value, length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_countdown_handle
功能描述 : 针对DPID_COUNTDOWN的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_countdown_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为VALUE
    unsigned char ret;
    unsigned long countdown;
    
    countdown = mcu_get_dp_download_value(value,length);
    
    DpDownloadCountdownHandle(countdown);
    
    /*
    //VALUE type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_value_update(DPID_COUNTDOWN,countdown);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_music_data_handle
功能描述 : 针对DPID_MUSIC_DATA的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 只下发类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_music_data_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为STRING
    unsigned char ret;
    /*
    //STRING type data processing
    unsigned char string_data[8];
    
    string_data[0] = value[0];
    string_data[1] = value[1];
    string_data[2] = value[2];
    string_data[3] = value[3];
    string_data[4] = value[4];
    string_data[5] = value[5];
    string_data[6] = value[6];
    string_data[7] = value[7];
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_string_update(DPID_MUSIC_DATA,value, length);
    
    DpDownloadMusicDataHandle(value, length);
    
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_control_data_handle
功能描述 : 针对DPID_CONTROL_DATA的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 只下发类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_control_data_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为STRING
    unsigned char ret;
    /*
    //STRING type data processing
    unsigned char string_data[8];
    
    string_data[0] = value[0];
    string_data[1] = value[1];
    string_data[2] = value[2];
    string_data[3] = value[3];
    string_data[4] = value[4];
    string_data[5] = value[5];
    string_data[6] = value[6];
    string_data[7] = value[7];
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_string_update(DPID_CONTROL_DATA,value, length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_rhythm_mode_handle
功能描述 : 针对DPID_RHYTHM_MODE的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_rhythm_mode_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_RHYTHM_MODE,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_sleep_mode_handle
功能描述 : 针对DPID_SLEEP_MODE的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_sleep_mode_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_SLEEP_MODE,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_wakeup_mode_handle
功能描述 : 针对DPID_WAKEUP_MODE的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_wakeup_mode_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_WAKEUP_MODE,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_power_memory_handle
功能描述 : 针对DPID_POWER_MEMORY的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_power_memory_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_POWER_MEMORY,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_do_not_disturb_handle
功能描述 : 针对DPID_DO_NOT_DISTURB的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_do_not_disturb_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为BOOL
    unsigned char ret;
    //0:off/1:on
    unsigned char do_not_disturb;
    
    do_not_disturb = mcu_get_dp_download_bool(value,length);
    
    DpDownloadDoNotDsturbHandle(do_not_disturb);
    
    if(do_not_disturb == 0) {
        //bool off
    }else {
        //bool on
    }
  
    //There should be a report after processing the DP
    ret = mcu_dp_bool_update(DPID_DO_NOT_DISTURB,do_not_disturb);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_switch_gradient_handle
功能描述 : 针对DPID_SWITCH_GRADIENT的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_switch_gradient_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_SWITCH_GRADIENT,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_mix_light_scene_handle
功能描述 : 针对DPID_MIX_LIGHT_SCENE的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_mix_light_scene_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_MIX_LIGHT_SCENE,value,length);
    
    DpDownloadMixLightSceneHandle(value, length);
    
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_mix_rgbcw_handle
功能描述 : 针对DPID_MIX_RGBCW的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_mix_rgbcw_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_MIX_RGBCW,value,length);
    
    DpDownloadMixRgbcwHandle(value, length);
    
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_segment_dimming_handle
功能描述 : 针对DPID_SEGMENT_DIMMING的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_segment_dimming_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_SEGMENT_DIMMING,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_switch_night_light_handle
功能描述 : 针对DPID_SWITCH_NIGHT_LIGHT的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_switch_night_light_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为BOOL
    unsigned char ret;
    //0:off/1:on
    unsigned char switch_night_light;
    
    switch_night_light = mcu_get_dp_download_bool(value,length);
    
    DpDownloadSwitchNightLightHandle(switch_night_light);
        
    if(switch_night_light == 0) {
        //bool off
    }else {
        //bool on
    }
  
    //There should be a report after processing the DP
    ret = mcu_dp_bool_update(DPID_SWITCH_NIGHT_LIGHT,switch_night_light);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_zll_value_handle
功能描述 : 针对DPID_ZLL_VALUE的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_zll_value_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为VALUE
    unsigned char ret;
    unsigned long zll_value;
    
    zll_value = mcu_get_dp_download_value(value,length);
    /*
    //VALUE type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_value_update(DPID_ZLL_VALUE,zll_value);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_cycle_timing_handle
功能描述 : 针对DPID_CYCLE_TIMING的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_cycle_timing_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_CYCLE_TIMING,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}
/*****************************************************************************
函数名称 : dp_download_random_timing_handle
功能描述 : 针对DPID_RANDOM_TIMING的处理函数
输入参数 : value:数据源数据
        : length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_random_timing_handle(const unsigned char value[], unsigned short length)
{
    //示例:当前DP类型为RAW
    unsigned char ret;
    /*
    //RAW type data processing
    
    */
    
    //There should be a report after processing the DP
    ret = mcu_dp_raw_update(DPID_RANDOM_TIMING,value,length);
    if(ret == SUCCESS)
        return SUCCESS;
    else
        return ERROR;
}




#ifdef SUPPORT_MCU_RTC_CHECK
/**
* @brief mcu check local RTC time 
* @param[in] {time} timestamp
* @return  void
*/
void mcu_write_rtctime(unsigned char time[])
{
  #error "mcu should realize RTC time wtriting fuction, and delete this line"
  /*
  time[0]~time[3]：standard time
  time[4]~time[7]: Local time
 */
	my_memcpy((void *)timestamp,(const char *)time,4);	//get timestamp
	zigbee_timestamp_to_time();	
/*
	year = _time.w_year;	//year
	month = _time.w_month;	//month
	date = _time.w_date;	//date
	hour = _time.hour + 8;	//hour(8:BeiJing time)
	min = _time.min;	//minute
	sec = _time.sec;	//second
*/
}
#endif


/**
* @brief Zigbee functional test feedback
* @param[in] {void} 
* @return  void
*/
void zigbee_test_result(void)
{
//	#error "this test is makesure the rf fuction of zigbee module, if test pass or not should do something, mcu should realize"
	unsigned char rssi = zigbee_uart_rx_buf[DATA_START+1];

	if(zigbee_uart_rx_buf[DATA_START]== 0x01){
		if(rssi > 0x3C)	{
			//test sucess the range of rssi is 0% ~ 100%
		}
		else{
			//test failure
		}
	}
	else{
		//test failure
	}
}

/******************************************************************************
                                WARNING!!!                     
以下函数用户请勿修改!!
******************************************************************************/

/**
* @brief this function will handle uart received frame data  
* @param[in] {dpid}   dp id
* @param[in] {value}  dp data 
* @param[in] {length} lenght of dp data 
* @return  handle result 
*/
unsigned char dp_download_handle(unsigned char dpid,const unsigned char value[], unsigned short length)
{
  /* only list of function, mcu need realize these fuction*/
  unsigned char ret;
  switch(dpid){
          case DPID_SWITCH_LED:
            //开关处理函数
            ret = dp_download_switch_led_handle(value,length);
        break;
        case DPID_WORK_MODE:
            //模式处理函数
            ret = dp_download_work_mode_handle(value,length);
        break;
        case DPID_BRIGHT_VALUE:
            //亮度值处理函数
            ret = dp_download_bright_value_handle(value,length);
        break;
        case DPID_TEMP_VALUE:
            //冷暖值处理函数
            ret = dp_download_temp_value_handle(value,length);
        break;
        case DPID_COLOUR_DATA:
            //彩光处理函数
            ret = dp_download_colour_data_handle(value,length);
        break;
        case DPID_SCENE_DATA:
            //情景处理函数
            ret = dp_download_scene_data_handle(value,length);
        break;
        case DPID_COUNTDOWN:
            //倒计时剩余时间处理函数
            ret = dp_download_countdown_handle(value,length);
        break;
        case DPID_MUSIC_DATA:
            //音乐灯处理函数
            ret = dp_download_music_data_handle(value,length);
        break;
        case DPID_CONTROL_DATA:
            //调节处理函数
            ret = dp_download_control_data_handle(value,length);
        break;
        case DPID_RHYTHM_MODE:
            //生物节律处理函数
            ret = dp_download_rhythm_mode_handle(value,length);
        break;
        case DPID_SLEEP_MODE:
            //入睡处理函数
            ret = dp_download_sleep_mode_handle(value,length);
        break;
        case DPID_WAKEUP_MODE:
            //唤醒处理函数
            ret = dp_download_wakeup_mode_handle(value,length);
        break;
        case DPID_POWER_MEMORY:
            //上电状态处理函数
            ret = dp_download_power_memory_handle(value,length);
        break;
        case DPID_DO_NOT_DISTURB:
            //勿扰模式处理函数
            ret = dp_download_do_not_disturb_handle(value,length);
        break;
        case DPID_SWITCH_GRADIENT:
            //开关渐变处理函数
            ret = dp_download_switch_gradient_handle(value,length);
        break;
        case DPID_MIX_LIGHT_SCENE:
            //混光场景处理函数
            ret = dp_download_mix_light_scene_handle(value,length);
        break;
        case DPID_MIX_RGBCW:
            //混光处理函数
            ret = dp_download_mix_rgbcw_handle(value,length);
        break;
        case DPID_SEGMENT_DIMMING:
            //分段调光处理函数
            ret = dp_download_segment_dimming_handle(value,length);
        break;
        case DPID_SWITCH_NIGHT_LIGHT:
            //夜灯开关处理函数
            ret = dp_download_switch_night_light_handle(value,length);
        break;
        case DPID_ZLL_VALUE:
            //zigbee light link阀值处理函数
            ret = dp_download_zll_value_handle(value,length);
        break;
        case DPID_CYCLE_TIMING:
            //循环定时处理函数
            ret = dp_download_cycle_timing_handle(value,length);
        break;
        case DPID_RANDOM_TIMING:
            //随机定时处理函数
            ret = dp_download_random_timing_handle(value,length);
        break;

  
  default:
    break;
  }
  return ret;
}

/**
* @brief get received cmd total number
* @param[in] {void}   
* @return  received cmd total number
*/
unsigned char get_download_cmd_total(void)
{
  return(sizeof(download_cmd) / sizeof(download_cmd[0]));
}


/**
* @brief received zigbee net_work state handle 
* @param[in] {zigbee_work_state}  zigbee current network state
* @return  void 
*/
void zigbee_work_state_event(unsigned char zigbee_work_state)
{	
	unsigned short length= 0;
	zigbee_uart_write_frame(ZIGBEE_STATE_CMD, length);	
    
    ZigbeeWorkStateEvent(zigbee_work_state);
    
	switch(zigbee_work_state){
		case ZIGBEE_NOT_JION:	

			break;
		
		case ZIGBEE_JOIN_GATEWAY:	

			break;
		
		case ZIGBEE_JOIN_ERROR:	

			break;
		
		case ZIGBEE_JOINING:	

			break;
		
		default:
			break;
	}
}


/**
* @brief received reset zigbee response 
* @param[in] {state} response state 
* @return  void 
*/
void mcu_reset_zigbee_event(unsigned char state)
{	
	switch(state){
		case RESET_ZIGBEE_OK:
		
			break;
		
		case RESET_ZIGBEE_ERROR:
		
			break;
		
		default:
			break;
	}
}


/**
* @brief check mcu version response
* @param[in] {void}
* @return  void 
*/
void response_mcu_ota_version_event(void)
{
	unsigned short length = 0;
	length = set_zigbee_uart_byte(length,get_current_mcu_fw_ver());	//current fw version
	zigbee_uart_write_frame(MCU_OTA_VERSION_CMD,length);
}

#ifdef SUPPORT_MCU_OTA
/**
* @brief mcu ota update notify response
* @param[in] {offset} data offset 
* @return  void 
*/
void response_mcu_ota_notify_event(unsigned char offset)
{
	unsigned char i = 0;
	unsigned short length = 0;
	
	current_mcu_fw_pid();	//current PID
	
	while(i<8){
		ota_fw_info.mcu_ota_pid[i] = zigbee_uart_rx_buf[offset + DATA_START + i];								//ota fw PID
		i++;
	}
	ota_fw_info.mcu_ota_ver = zigbee_uart_rx_buf[offset + DATA_START + 8];											//ota fw version
	ota_fw_info.mcu_ota_fw_size = zigbee_uart_rx_buf[offset + DATA_START + 9] << 24 | \
																zigbee_uart_rx_buf[offset +DATA_START + 10] << 16 | \
																zigbee_uart_rx_buf[offset + DATA_START + 11] << 8 | \
																zigbee_uart_rx_buf[offset + DATA_START + 12];								//ota fw size
	ota_fw_info.mcu_ota_checksum = zigbee_uart_rx_buf[offset + DATA_START + 13] << 24 | \
																 zigbee_uart_rx_buf[offset + DATA_START + 14] << 16 | \
																 zigbee_uart_rx_buf[offset + DATA_START + 15] << 8 | \
																 zigbee_uart_rx_buf[offset + DATA_START + 16];								//ota fw checksum
	
	if((!strcmp_barry(&ota_fw_info.mcu_ota_pid[0],&current_mcu_pid[0],8)) && \
		 (ota_fw_info.mcu_ota_ver > get_current_mcu_fw_ver() &&\
		  ota_fw_info.mcu_ota_fw_size > 0)	
		){		//check fw pid and fw version and fw size
		length = set_zigbee_uart_byte(length,0x00);	//OK
	}
	else{
		length = set_zigbee_uart_byte(length,0x01);	//error
	}
    ota_fw_info.mcu_current_offset = 0;
	zigbee_uart_write_frame(MCU_OTA_NOTIFY_CMD,length);
}


/**
* @brief received mcu ota data request response
* @param[in] {fw_offset}  offset of file 
* @param[in] {data}  received data  
* @return  void 
*/
void reveived_mcu_ota_data_handle(unsigned int fw_offset,char *data)
{
	#error "received frame data, should save in flash, mcu should realize this fuction, and delete this line "
}

/**
* @brief mcu send ota data request 
* @param[in] {void}  
* @return  void 
*/
void mcu_ota_fw_request_event(unsigned char offset)
{	
	unsigned int fw_offset = 0;
	char fw_data[FW_SINGLE_PACKET_SIZE] = {-1};	//
	unsigned char i = 0;
	unsigned char last_package_len = 0;
	static unsigned int current_checksum = 0;

	if(zigbee_uart_rx_buf[offset + DATA_START] == 0x01)				//status check
		return;
	while(i < 8){
		if(current_mcu_pid[i] != zigbee_uart_rx_buf[offset + DATA_START + 1 + i])	//pid check
			return;
		i++;
	}
	if(ota_fw_info.mcu_ota_ver != zigbee_uart_rx_buf[offset + DATA_START + 9]) //version check
		return;
	
	i = 0;
	while(i < 4){
		fw_offset |= (zigbee_uart_rx_buf[offset + DATA_START + 10 + i] << (24 - i * 8));		//offset
		i++;
	}
	i = 0;
	if(ota_fw_info.mcu_current_offset ==  fw_offset)
	{
		if((ota_fw_info.mcu_ota_fw_size - fw_offset) / FW_SINGLE_PACKET_SIZE != 0){
			if(ota_fw_info.mcu_current_offset == 0){
				current_checksum = 0;
			}
			while(i < FW_SINGLE_PACKET_SIZE){
				fw_data[i] = zigbee_uart_rx_buf[offset + DATA_START + 14 + i];   //fw data
				current_checksum += fw_data[i];
				i++;
			}
			ota_fw_info.mcu_current_offset += FW_SINGLE_PACKET_SIZE;
			ota_fw_data_handle(fw_offset,&fw_data[0],FW_SINGLE_PACKET_SIZE);	//OTA paket data handle
		}
		else {
			i = 0;
			last_package_len = ota_fw_info.mcu_ota_fw_size - fw_offset;
			while(i < last_package_len){
				fw_data[i] = zigbee_uart_rx_buf[offset + DATA_START + 14 + i];
				current_checksum += fw_data[i];
				i++;
			}
			ota_fw_info.mcu_current_offset += last_package_len;
			if(ota_fw_info.mcu_ota_checksum != current_checksum){
				//ota failure report ota failure and clear ota struct 
				mcu_ota_result_report(1); // failed
			}	
			else{
				//ota sucess 
				mcu_ota_result_report(0); // seccess
			}
			ota_fw_data_handle(fw_offset,&fw_data[0],last_package_len);	//OTA paket data handle		
			current_checksum = 0;															
		}
	}
	else
	{
		// ota request timeout, then restart ota request from  ota_fw_info.mcu_ota_fw_size
	}
}

static void report_mcu_ota_result(unsigned char  res)
{
	unsigned short length;
	if((res==0)||(res == 1))
	{
		length = set_zigbee_uart_byte(length,res);	
		zigbee_uart_write_frame(MCU_OTA_NOTIFY_CMD,length);
	}
}


/**
* @brief mcu ota data result notify
* @param[in] {void} 
* @return  void 
*/
void mcu_ota_result_event(unsigned char offset)
{
	unsigned char status = zigbee_uart_rx_buf[offset + DATA_START];
	
	if(status == 0x00){
	}
	else if(status == 0x01)	{

	}
}

/**
* @brief mcu ota data handle 
* @param[in] {fw_offset} frame offset 
* @param[in] {data} received data
* @return  void 
*/
void ota_fw_data_handle(unsigned int fw_offset,char *data,unsigned char data_len)
{
	#error "请在该函数处理固件包数据,并删除该行"
}
#endif


#ifdef  BEACON_TEST
/**
* @brief beacon test notify,which used in testing
* @param[in] {void} 
* @return  void 
*/
void mcu_received_beacon_test_handle(void)
{
	unsigned short length = 0;
	length = set_zigbee_uart_byte(length,0x00);	
	zigbee_uart_write_frame(SEND_BEACON_NOTIFY_CMD,length);
	// then start test
}
#endif

#ifdef  CHECK_ZIGBEE_NETWORK
/**
* @brief check zigbee nwkstate,before start join nwk, check nwk if state is not 0x02,can start jion,
* else delay 5s 
*
* @param[in] {void} 
* @return  void 
*/
void mcu_check_zigbee_nwk_state(void)
{
	unsigned short length = 0;
	zigbee_uart_write_frame(CHECK_ZIGBEE_NETWORK_CMD,length);
	// then start test
}
#endif

void zigbee_notify_factory_new_hanlde(void)
{
	unsigned short length = 0;
	length = set_zigbee_uart_byte(length,0x01);	
	zigbee_uart_write_frame(ZIGBEE_FACTORY_NEW_CMD,length);
	// then start test
}


#ifdef READ_DP_DATA_NOTIFY
/**
* @brief when gateway repower or relink clould, or zigbee module join sucess, repower, this commod will notify 
* mcu, to sys dp data, mcu itself decide whether report.
*
* @param[in] {void} 
* @return  void 
*/
void read_dp_data_notify_hanlde(void)
{
	unsigned short length = 0;
	length = set_zigbee_uart_byte(length,0x01);	
	zigbee_uart_write_frame(ZIGBEE_FACTORY_NEW_CMD,length);
	// then start test
}
#endif 



